package com.hjyang.doc.convert.pdf.doc.conver;

import com.gsafety.fileauxiliarysystem.utils.doc.config.ConfigBean;
import com.lowagie.text.pdf.BaseFont;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.converter.PicturesManager;
import org.apache.poi.hwpf.converter.WordToHtmlConverter;
import org.apache.poi.hwpf.usermodel.Picture;
import org.apache.poi.hwpf.usermodel.PictureType;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Entities;
import org.w3c.dom.Document;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.util.List;

/**
 * DocToPdf
 */
public class DocToPdf {
    public static void main(String[] args) {
        try {
            word2pdf("D:/word2pdfFile/123.doc", "D:/word2pdfFile/123.pdf");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * word文档转pdf
     *
     * @param wordFilePath word文档路径
     * @param pdfFilePath  pdf文档输出路径
     */
    public static String word2pdf(String wordFilePath, String pdfFilePath) {
        File wordFile = new File(wordFilePath);
        File pdfFile = new File(pdfFilePath);
        return word2pdf(wordFile, pdfFile);
    }

    /**
     * word文档转pdf
     *
     * @param wordFile word文档File对象
     * @param pdfFile  pdfFile对象
     */
    public static String word2pdf(File wordFile, File pdfFile){
        String wordName = wordFile.getName();
        if (!wordName.endsWith(".doc") && !wordName.endsWith(".docx")) {
            return null;
        }
        File pdfParentFile = pdfFile.getParentFile();
        if (!pdfParentFile.exists()) {
            pdfParentFile.mkdirs();
        }
        String absolutePath = pdfParentFile.getAbsolutePath();
        wordName = wordName.substring(0, wordName.indexOf("."));
        String htmlPath = absolutePath + File.separator + wordName + ".html";
        File htmlFile = new File(htmlPath);
        // doc格式word文档，先转成html，再格式化标签成xhtml，最后转成pdf
        wordDocToHtml(wordFile, htmlFile);
        try {
            convertHtmlToPdf(htmlFile, pdfFile);
        } catch (Exception e) {
            e.printStackTrace();
            return "html";
        }
        // 删除html文件
        htmlFile.delete();
        return "pdf";
    }

    /**
     * doc转html
     *
     * @param wordFile
     * @param htmlFile
     */
    private static boolean wordDocToHtml(File wordFile, File htmlFile) {
        if (null == wordFile || null == htmlFile) {
            return false;
        }
        File parentFile = htmlFile.getParentFile();
        if (!parentFile.exists()) {
            parentFile.mkdirs();
        }
        String absolutePath = parentFile.getAbsolutePath();
        HWPFDocument wordDocument;
        final String imagepath = absolutePath + "/temp/wordimage/";
        try {
            // 根据输入文件路径与名称读取文件流
            InputStream in = new FileInputStream(wordFile);
            // 把文件流转化为输入wordDom对象
            wordDocument = new HWPFDocument(in);
            // 通过反射构建dom创建者工厂
            DocumentBuilderFactory domBuilderFactory = DocumentBuilderFactory.newInstance();
            // 生成dom创建者
            DocumentBuilder domBuilder = domBuilderFactory.newDocumentBuilder();
            // 生成dom对象
            Document dom = domBuilder.newDocument();
            // 生成针对Dom对象的转化器
            WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(dom);
            // 转化器重写内部方法
            wordToHtmlConverter.setPicturesManager(new PicturesManager() {
                @Override
                public String savePicture(byte[] content, PictureType pictureType, String suggestedName, float widthInches, float heightInches) {
                    File imgPath = new File(imagepath);
                    if (!imgPath.exists()) {// 图片目录不存在则创建
                        imgPath.mkdirs();
                    }
                    File file = new File(imagepath + suggestedName);
                    try {
                        OutputStream os = new FileOutputStream(file);
                        os.write(content);
                        os.close();
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return imagepath + suggestedName;
                }
            });
            // 转化器开始转化接收到的dom对象
            wordToHtmlConverter.processDocument(wordDocument);
            // 保存文档中的图片
            List<?> pics = wordDocument.getPicturesTable().getAllPictures();
            if (pics != null) {
                for (int i = 0; i < pics.size(); i++) {
                    Picture pic = (Picture) pics.get(i);
                    try {
                        pic.writeImageContent(new FileOutputStream(imagepath + pic.suggestFullFileName()));
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                }
            }
            // 从加载了输入文件中的转换器中提取DOM节点
            Document htmlDocument = wordToHtmlConverter.getDocument();
            // 从提取的DOM节点中获得内容
            DOMSource domSource = new DOMSource(htmlDocument);
            // 字节码输出流
            OutputStream out = new FileOutputStream(htmlFile);
            // 输出流的源头
            StreamResult streamResult = new StreamResult(out);
            // 转化工厂生成序列转化器
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer serializer = tf.newTransformer();
            // 设置序列化内容格式
            serializer.setOutputProperty(OutputKeys.ENCODING, "Unicode");//此处根据你 的word文档的编码格式进行设置
            serializer.setOutputProperty(OutputKeys.INDENT, "yes");
            serializer.setOutputProperty(OutputKeys.METHOD, "html");
            serializer.transform(domSource, streamResult);
            out.close();
            in.close();
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        } catch (IOException e1) {
            e1.printStackTrace();
        } catch (TransformerConfigurationException e) {
            e.printStackTrace();
        } catch (TransformerException e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        }
        return true;
    }

    /**
     * html转pdf
     *
     * @param htmlFile
     * @param pdfFile
     * @return
     * @throws Exception
     */
    private static boolean convertHtmlToPdf(File htmlFile, File pdfFile) throws Exception {
        if (null == htmlFile || null == pdfFile) {
            return false;
        }
        String absoluteFilePath = htmlFile.getParentFile().getAbsolutePath();
        if (!pdfFile.getParentFile().exists()) {
            pdfFile.getParentFile().mkdirs();
        }
        // .doc转成的html中有些标签：例如<mate>不严谨，会出现标签不闭合问题，在转pdf时会报异常，故此处用jsoup将html转化成xhtml，将标签严谨
        // 格式化html标签
        org.jsoup.nodes.Document parse = Jsoup.parse(htmlFile, "utf-8");
        parse.outputSettings().syntax(org.jsoup.nodes.Document.OutputSettings.Syntax.xml).escapeMode(Entities.EscapeMode.xhtml);
        String html = parse.html();
        // 此处将body标签中的字体设置为SimSun，必须是这种样式，才会识别中文支持的文件，如果不设置，会出现转成的pdf中文不显示问题（此处�?要替换的字段，可用将自己转成的html打印出来，查看是否是宋体，如不是，将宋体改为你转换成html的字体格式）
        String regex = "font-family(.*?);";
        regex = "font-family(.*?);";
        html = html.replaceAll(regex, "font-family:SimSun;");
        html = html.replaceAll("<img src=\"", "<img src=\"file:");
        OutputStream os = new FileOutputStream(pdfFile);
        ITextRenderer renderer = new ITextRenderer();
        renderer.setDocumentFromString(html);
        // 解决中文支持问题
        ITextFontResolver fontResolver = renderer.getFontResolver();
        //fontResolver.addFont("D:/word2pdfFile/simsun.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        fontResolver.addFont(ConfigBean.getFontPath(), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        // 解决图片的相对路径问问题
        renderer.getSharedContext().setBaseURL(absoluteFilePath + File.separator + "temp/wordimage/");
        renderer.layout();
        renderer.createPDF(os);
        os.flush();
        os.close();
        return true;
    }
}
